﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using Common;

namespace TwoItems
{
    public class DecentralizedAlg
    {
        /// <summary>
        /// 
        /// </summary>
        public double Tolerences { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public double RepeatTimes { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public double MaxIteration { get; set; }

        public void RunComputing(ExampleInfo example)
        {
            example.MaxQD1 = NormDistHelper.QNorm(example.UO1, example.E1, example.SD1);
            example.MaxQD2 = NormDistHelper.QNorm(example.UO2, example.E2, example.SD2);

            example.QD1 = NormDistHelper.QNorm(example.UO1, example.E1, example.SD1);
            example.QD2 = NormDistHelper.QNorm(example.UO2, example.E2, example.SD2);

            //迭代
            bool stop = false;
            //存储连续小于容忍值的迭代
            int repeates = 0;

            for (int j = 0; ; j++)
            {
                if (stop)
                {
                    Trace.WriteLine("迭代结束!");
                    break;
                }
                if (j >= MaxIteration)//超出最大迭代次数
                {
                    Trace.WriteLine("超出最大迭代次数,结束!");
                    break;
                }


                //double qd1 = example.QD1;
                //double qd2 = example.QD2;

                //if (qd1 < 0 || qd2 < 0)
                //{
                //    Trace.WriteLine("出现负数!");
                //    break;
                //}

                //todo:在此，记录每次迭代的数据，观察收敛效果
                double error = IterateOnce(example);
                if (error < Tolerences)
                    repeates += 1;
                else//出现任意一次不能接受，重置计数器
                    repeates = 0;

                //判断是否连续N次可以接受
                if (repeates >= RepeatTimes)
                    stop = true;

                //Trace.WriteLine(string.Format("第{0}次迭代,Error={1},QD1={2},QD2={3}", j, error, qd1, qd2));
                //Trace.WriteLine(example.PD + "\t" + error);
            }


            Profit(example);

            Trace.WriteLine(example.PD);

        }
        /// <summary>
        /// 一次迭代
        /// </summary>
        /// <param name="example"></param>
        /// <returns>误差e^2</returns>
        private double IterateOnce(ExampleInfo example)
        {
            double u1 = example.U1;
            double o1 = example.O1;
            double u2 = example.U2;
            double o2 = example.O2;

            double e1 = example.E1;
            double e2 = example.E2;
            double sd1 = example.SD1;
            double sd2 = example.SD2;

            double var1 = example.Var1;
            double var2 = example.Var2;

            double qd1 = example.QD1;
            double qd2 = example.QD2;

            double r12 = example.R12;
            double r21 = example.R21;


            //计算有效需求的期望和标准差
            double gama1 = (qd1 - ((qd1 - e1) * NormDistHelper.PNorm(qd1, e1, sd1) + var1 * NormDistHelper.DNorm(qd1, e1, sd1))) / e1;
            double gama2 = (qd2 - ((qd2 - e2) * NormDistHelper.PNorm(qd2, e2, sd2) + var2 * NormDistHelper.DNorm(qd2, e2, sd2))) / e2;

            double e1_e = e1 - r21 * e2 * (1 - gama2);
            double sd1_e = Math.Sqrt(var1 + Math.Pow(r21 * sd2 * (1 - gama2), 2));

            double e2_e = e2 - r12 * e1 * (1 - gama1);
            double sd2_e = Math.Sqrt(var2 + Math.Pow(r12 * sd1 * (1 - gama1), 2));

            //double var1 = example.Var1;
            //double var2 = example.Var2;

            ////计算有效需求的期望和标准差
            //double pnorm1 = NormDistHelper.PNorm(example.QD1, example.E1, example.SD1);
            //double gama1 = pnorm1 + (example.QD1 * (1 - pnorm1) - (var1) * NormDistHelper.DNorm(example.QD1, example.E1, example.SD1)) / example.E1;

            //double pnorm2 = NormDistHelper.PNorm(example.QD2, example.E2, example.SD2);
            //double gama2 = pnorm2 + (example.QD2 * (1 - pnorm2) - var2 * NormDistHelper.DNorm(example.QD2, example.E2, example.SD2)) / example.E2;

            //double e1_e = example.E1 - example.R21 * example.E2 * (1 - gama2);//有效需要的期望
            //double sd1_e = Math.Sqrt(var1 + Math.Pow(example.R21 * example.SD2 * (1 - gama2), 2));//有效需要的标准差

            //double e2_e = example.E2 - example.R12 * example.E1 * (1 - gama1);//有效需要的期望
            //double sd2_e = Math.Sqrt(var2 + Math.Pow(example.R12 * example.SD1 * (1 - gama1), 2));//有效需要的标准差


            double nextQd1 = NormDistHelper.QNorm(u1 / (u1 + o1), e1_e, sd1_e);
            double nextQd2 = NormDistHelper.QNorm(u2 / (u2 + o2), e2_e, sd2_e);

            //判断误差Error

            //计算出来的概率
            double prob1_e = NormDistHelper.PNorm(qd1, e1_e, sd1_e);
            double prob2_e = NormDistHelper.PNorm(qd2, e2_e, sd2_e);

            example.Prob1 = prob1_e;
            example.Prob2 = prob2_e;


            example.QD1 = nextQd1;
            example.QD2 = nextQd2;


            //已经推导出来利润

            //example.PD1 = (u1 + o1) *
            //              ((e1_e - qd1) * NormDistHelper.PNorm(qd1, e1_e, sd1_e) - sd1_e * sd1_e * NormDistHelper.DNorm(qd1, e1_e, sd1_e)) +
            //              u1 * qd1;

            //example.PD2 = (u2 + o2) *
            //              ((e2_e - qd2) * NormDistHelper.PNorm(qd2, e2_e, sd2_e) - sd2_e * sd2_e * NormDistHelper.DNorm(qd2, e2_e, sd2_e)) +
            //              u2 * qd2;

           

            //Trace.WriteLine(example.PD + "\t" + error);
            return Math.Pow(Math.Abs(prob1_e - example.UO1) / example.UO1, 2) +
                   Math.Pow(Math.Abs(prob2_e - example.UO2) / example.UO2, 2);
        }

        public void Profit(ExampleInfo example)
        {
            double u1 = example.U1;
            double o1 = example.O1;
            double u2 = example.U2;
            double o2 = example.O2;

            double e1 = example.E1;
            double e2 = example.E2;
            double sd1 = example.SD1;
            double sd2 = example.SD2;

            double var1 = example.Var1;
            double var2 = example.Var2;

            double qd1 = example.QD1;
            double qd2 = example.QD2;

            double r12 = example.R12;
            double r21 = example.R21;


            //计算有效需求的期望和标准差
            double gama1 = (qd1 - ((qd1 - e1) * NormDistHelper.PNorm(qd1, e1, sd1) + var1 * NormDistHelper.DNorm(qd1, e1, sd1))) / e1;
            double gama2 = (qd2 - ((qd2 - e2) * NormDistHelper.PNorm(qd2, e2, sd2) + var2 * NormDistHelper.DNorm(qd2, e2, sd2))) / e2;

            double e1_e = e1 - r21 * e2 * (1 - gama2);
            double sd1_e = Math.Sqrt(var1 + Math.Pow(r21 * sd2 * (1 - gama2), 2));

            double e2_e = e2 - r12 * e1 * (1 - gama1);
            double sd2_e = Math.Sqrt(var2 + Math.Pow(r12 * sd1 * (1 - gama1), 2));
            example.PD1 = u1 * qd1 -
                           (u1 + o1) * ((qd1 - e1_e) * NormDistHelper.PNorm(qd1, e1_e, sd1_e) +
                            sd1_e * sd1_e * NormDistHelper.DNorm(qd1, e1_e, sd1_e));

            example.PD2 = u2 * qd2 -
                           (u2 + o2) *
                           ((qd2 - e2_e) * NormDistHelper.PNorm(qd2, e2_e, sd2_e) +
                            sd2_e * sd2_e * NormDistHelper.DNorm(qd2, e2_e, sd2_e));


            example.PD = example.PD1 + example.PD2;
        }
    }
}
